package dbb

import (
	"reflect"
	"strings"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/data/binding"
	"fyne.io/fyne/v2/dialog"
	"fyne.io/fyne/v2/storage"
	"fyne.io/fyne/v2/theme"
	"fyne.io/fyne/v2/widget"
	"github.com/gogf/gf/v2/container/garray"
	"github.com/gogf/gf/v2/container/gmap"
	"github.com/gogf/gf/v2/database/gdb"
	osdlg "github.com/sqweek/dialog"
	"github.com/y2h/fyne_poem/util"
	"github.com/y2h/fyne_poem/widgets"
)

// List2Slice 用列表控件显示二维字符串切片
// dd[i][j]
// dd := [][]string{}
// for i := 0; i < len(data[thisTbl]); i++ {
// 	sdata := "select " + data[thisTbl][i] + " from " + thisTbl +
// 		" order by " + data[thisTbl][0] + " desc limit 20"
// 	d := GetOneCol(db, sdata, msg)
// 	dd = append(dd, d)
// }
//lst1 := List2SliceBtn(dd, data[thisTbl], nil)
func List2SliceBtn(db gdb.DB, tbl string, msg *widget.Label,
	dd [][]string, header []string, w fyne.Window) *widget.List {
	ldd := len(dd) // 返回列数
	lst := widget.NewList(func() int {
		return len(dd[0]) + 1 // 返回行数
	}, func() fyne.CanvasObject {
		hbox1 := container.NewGridWithColumns(ldd + 2)
		for i := 0; i < ldd; i++ {
			lbl := widget.NewLabelWithStyle("table", fyne.TextAlignCenter,
				fyne.TextStyle{})
			lbl.Wrapping = fyne.TextTruncate
			hbox1.Add(lbl)
		}
		//hbox1.Add(PopUpBtn(nil, w))
		hbox1.Add(widget.NewButton("edit", nil))
		hbox1.Add(widget.NewButton("delete", nil))
		return hbox1
	}, func(lii widget.ListItemID, co fyne.CanvasObject) {
		box := co.(*fyne.Container)
		if lii == 0 {
			for i := 0; i < ldd; i++ {
				//btn := widget.NewButton(header[i], nil)
				//box.Objects[i] = btn
				lbl := widget.NewLabel(header[i])
				box.Objects[i] = lbl
			}
			box.Objects[len(header)] = widget.NewLabel("")
			box.Objects[len(header)+1] = widget.NewLabel("")
			return
		} else {
			for i := 0; i < ldd; i++ {
				if reflect.TypeOf(box.Objects[i]) == reflect.TypeOf(widget.NewLabel("")) {
					lbl := box.Objects[i].(*widget.Label)
					lbl.SetText(dd[i][lii-1])
				}
			}
			box.Objects[ldd].(*widget.Button).OnTapped = func() {
				frm := widget.NewForm()
				d := gmap.New()
				_, cols := SqliteTblColsGF(db, tbl)
				garray.NewStrArrayFrom(cols).
					Iterator(func(k int, v string) bool {
						txt := widget.NewEntry()
						txt.SetText(dd[k][lii-1])
						d.Set(v, txt)
						frm.Append(v, d.Get(v).(*widget.Entry))

						return true
					})
				frm.Append("", widget.NewButton("Submit", func() {
					dmap := gmap.New()
					d.Iterator(func(k, v interface{}) bool {
						dmap.Set(k, strings.TrimSpace(v.(*widget.Entry).Text))
						return true
					})
					_, err := db.Model(tbl).
						Where(header[0], dd[0][lii-1]).Update(dmap)

					if err != nil {
						msg.SetText("update err " + err.Error())
						return
					}
				}))

				msg.SetText("update success")
				w := fyne.CurrentApp().NewWindow("update record")
				w.Resize(fyne.NewSize(800, 700))
				w.SetContent(frm)
				w.Show()
			}
			box.Objects[ldd+1].(*widget.Button).OnTapped = func() {
				widgets.Confirm("Delete data", "Are you sure to delete "+dd[0][lii-1], w,
					func() {
						if lii < 1 {
							msg.SetText("please select a record")
							return
						}
						_, cols := SqliteTblColsGF(db, tbl)
						_, err := db.Model(tbl).Delete(cols[0], dd[0][lii-1])
						if err != nil {
							msg.SetText(err.Error())
							return
						}
						msg.SetText("delete" + dd[0][lii-1])
					}, func() {
						msg.SetText("cancel delete")
					})
			}
		}
	})

	return lst
}

// PopUpBtn 点击按钮弹出菜单
func PopUpBtn(popUpMenu *widget.PopUpMenu, w fyne.Window) *widget.Button {
	if popUpMenu == nil {
		menuItems := []*fyne.MenuItem{
			fyne.NewMenuItem("New", nil),
		}
		popUpMenu = widget.NewPopUpMenu(fyne.NewMenu("", menuItems...), w.Canvas())
	}
	d := fyne.CurrentApp().Driver()
	var button *widget.Button
	button = widget.NewButtonWithIcon("", theme.MoreVerticalIcon(), func() {
		buttonPos := d.AbsolutePositionForObject(button)
		buttonSize := button.Size()
		popUpMin := popUpMenu.MinSize()

		var popUpPos fyne.Position
		popUpPos.X = buttonPos.X + buttonSize.Width - popUpMin.Width
		popUpPos.Y = buttonPos.Y + buttonSize.Height
		popUpMenu.ShowAtPosition(popUpPos)
	})
	return button
}

func Table(data [][]string) *widget.Table {
	tbl1 := widget.NewTable(nil, nil, nil)
	tbl1.Length = func() (int, int) {
		// 处理首行是合并单元格的情况
		maxCol := 0
		for _, v := range data {
			maxCol = util.Max(maxCol, len(v))
		}
		return len(data), maxCol
		// return len(data), len(data[0])
	}
	tbl1.CreateCell = func() fyne.CanvasObject {
		return widget.NewLabel("table")
	}
	tbl1.UpdateCell = func(id widget.TableCellID, template fyne.CanvasObject) {
		lbl := template.(*widget.Label)
		// data1, err := f.GetRows("Sheet1"),为避免合并单元格造成数组越界
		// 如果数据为data1, err := f.GetCols("Sheet1")，则需要对id.Row进行越界检查
		if id.Col < len(data[id.Row]) {
			lbl.SetText(data[id.Row][id.Col])
		} else {
			lbl.SetText("")
		}
	}
	return tbl1
}

// 打开fyne框架对话框
func NewOpenFile1(data binding.String, filters []string,
	w fyne.Window) *fyne.Container {
	return container.NewBorder(nil, nil,
		widget.NewButtonWithIcon("", theme.FileIcon(), func() {
			d := dialog.NewFileOpen(func(uc fyne.URIReadCloser, e error) {
				if uc == nil {
					return
				}
				data.Set(uc.URI().String()[7:])
			}, w)
			luri, _ := storage.ListerForURI(storage.NewFileURI("."))

			d.SetFilter(storage.NewExtensionFileFilter(filters))
			d.SetLocation(luri)
			d.Show()
		}), nil,
		widget.NewEntryWithData(data))
}

// 打开系统原生对话框
func NewOpenFile(data binding.String, w fyne.Window) *fyne.Container {
	return container.NewBorder(nil, nil, widget.NewButtonWithIcon("", theme.FileIcon(), func() {
		s, err := osdlg.File().Filter("sqlite db", "db", "sqlite", "sqlite3").
			Title("Select a sqlite db").SetStartDir(".").Load()
		if err != nil {
			return
		}
		data.Set(s)
	}), nil,
		widget.NewEntryWithData(data))
}

// outData := binding.NewString()
// out := NewOpenFolder(outData, w)
// outData1 := binding.NewString()
// out1 := NewOpenFolder(outData1, w)
func NewOpenFolder(data binding.String, w fyne.Window) *fyne.Container {
	return container.NewBorder(nil, nil, widget.NewButtonWithIcon("", theme.FolderOpenIcon(), func() {
		d := dialog.NewFolderOpen(func(lu fyne.ListableURI, e error) {
			if lu == nil {
				return
			}
			data.Set(lu.Path())
		}, w)
		luri, _ := storage.ListerForURI(storage.NewFileURI("."))
		d.SetLocation(luri)
		d.Show()
	}), nil, widget.NewEntryWithData(data))
}
